package io.e2x.testground.fruitstore.service.impl;

import io.e2x.testground.fruitstore.dal.entities.Store;
import io.e2x.testground.fruitstore.dal.entities.StoreSpu;
import io.e2x.testground.fruitstore.repo.StoreRepo;
import io.e2x.testground.fruitstore.repo.StoreSpuRepo;
import io.e2x.testground.fruitstore.service.ProductService;
import io.e2x.testground.fruitstore.service.StoreService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.math.BigInteger;

@Component
public class StoreServiceImpl implements StoreService {

    @Autowired
    StoreRepo storeRepo;

    @Autowired
    StoreSpuRepo storeSpuRepo;
    @Autowired
    @Lazy
    ProductService productService;

    @Override
    public Flux<Store> getStores() {
        return storeRepo.findAll();
    }

    @Override
    public Mono<Void> addStore(Store store) {
        return ifNameNotExist(store.getName()).then(storeRepo.save(store)).then();
    }

    @Override
    public Mono<Void> addStoreSpus(StoreSpu storeSpu) {
        return isExist(storeSpu.getStoreId()).then(storeSpuRepo.save(storeSpu)).then();
    }

    @Override
    public Mono<Void> updateStoreSpus(StoreSpu storeSpu) {
        return isExist(storeSpu.getStoreId()).then(storeSpuRepo.save(storeSpu)).then();
    }

    @Override
    public Flux<StoreSpu> getStoreSpus(long storeId) {
        return isExist(storeId).thenMany(storeSpuRepo.findAllByStoreId(storeId));
    }

    @Override
    public Mono<Void> deleteStoreSpus(StoreSpu storeSpu) {
        return isExist(storeSpu.getStoreId()).then(storeSpuRepo.delete(storeSpu)).then();
    }

    @Override
    public Mono<StoreSpu> findStoreSpuBySpuNo(String spuNo) {
        return storeSpuRepo.findStoreSpuBySpuNo(spuNo);
    }

    @Override
    public Mono<StoreSpu> findStoreSpuByName(String name) {
        return productService.findBySpuName(name);
    }

    @Override
    public Mono<StoreSpu> findStoreSpuBySkuId(long id) {
        return storeSpuRepo.findBySkuId(id);
    }

    Mono<Void> isExist(long storeid) {
        return storeRepo.findById(storeid)
                .flatMap(store -> {
                    if (store == null) {
                        return Mono.error(new RuntimeException("店铺不存在"));
                    } else {
                        return Mono.empty();
                    }
                })
                .then();
    }

    Mono<Boolean> ifNameNotExist(String storeName) {
        return storeRepo.findByName(storeName)
                .hasElement()
                .doOnNext(exists -> {
                    if (exists) {
                        throw new RuntimeException("店铺名称已存在");
                    }
                });
    }
}
